Skip to content

Conversation

sajagana
Copy link
Collaborator

No description provided.

@sajagana sajagana force-pushed the nd_backup_schedule_new branch 2 times, most recently from e7eae7a to d018675 Compare August 20, 2025 12:05
@sajagana sajagana force-pushed the nd_backup_schedule_new branch from d018675 to a6465d2 Compare August 20, 2025 12:26
@sajagana sajagana changed the title Created nd_backup_schedule module using Ansible Network Resource Modules Approach Created nd_backup_schedule module using Ansible Network Resource Modules Approach (DCNE-496) Aug 20, 2025
@sajagana sajagana changed the base branch from master to codeowners August 20, 2025 14:17
@sajagana sajagana changed the base branch from codeowners to master August 20, 2025 14:18
@sajagana sajagana marked this pull request as ready for review August 20, 2025 14:19
state = nd.params.get("state")
schedules = nd.request(base_path, method="GET").get("schedules")

remote_schedule_map = wrap_objects_by_key(schedules)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assumption here is that you have a single identifier key, is this something that we would like to do?


result = compare_config_and_remote_objects(schedules, config)

if state != "query":
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems redundant because of the nd.exit_json() in line 209

nd.after = schedules
nd.exit_json()

nd.before = copy.deepcopy(schedules)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should before and after not both display the same output for query states ?


remote_schedule_map = wrap_objects_by_key(schedules)

if state == "query":
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we supposed to expose query state? If I look at the doc you shared it seems fact modules should handle this, but perhaps I misunderstand it.


nd.before = copy.deepcopy(schedules)

result = compare_config_and_remote_objects(schedules, config)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find the naming of this function a bit weird because the order of your function is reversed of your input to the function.

nd.after.append(payload)


def get_backup_schedule_time(scheduler_date, scheduler_time):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be a generic time handle utils function? likely we will need datetime formatting for other modules

Comment on lines +239 to +240
if not compare_unordered_list_of_dicts(nd.after, copy.deepcopy(nd.before)):
nd.result["changed"] = True
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this needed? cant we tell during a non GET request that is made already that there is a change?

nd.exit_json()


def post_backup_schedule_config(nd, module, path, config_obj, remote_obj=None, method="POST"):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure the function name really makes sense when the method can also be PUT


if state not in ["deleted", "absent"]:
for object in result.get("config_data_create"):
post_backup_schedule_config(nd, module, base_path, object)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did you investigate creating a generic request handler, and a module specific payload creator ( I assume that the end part of the function is repeatable for other modules )

config = nd.params.get("config")
state = nd.params.get("state")
schedules = nd.request(base_path, method="GET").get("schedules")

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generic overall question, did you consider usage of class structure in python? this way the repeatable conditionals could be done from a single class method, which makes the module perhaps more readable.

@@ -0,0 +1,67 @@
# -*- coding: utf-8 -*-
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we want to start to write unit tests for all these newly introduced utils function?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, I think we should be adding unit tests for util functions like these.

if key in sent:
try:
del sent[key]
except KeyError:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may not need this try/except around this anymore if key is being checked first.

def set_to_empty_string_when_none(self, val):
return val if val is not None else ""

def get_object_by_nested_key_value(self, path, nested_key_path, value, data_key=None):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a doc string explanation for this function?

@@ -0,0 +1,67 @@
# -*- coding: utf-8 -*-
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, I think we should be adding unit tests for util functions like these.

}


def compare_unordered_list_of_dicts(list1, list2):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this function also take into consideration that lists within the dictionaries could also be ordered different? Do we only need unordered comparison on the top level and not recursive?

---
module: nd_backup_schedule
version_added: "0.5.0"
short_description: Manages backup schedules on Cisco Nexus Dashboard.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
short_description: Manages backup schedules on Cisco Nexus Dashboard.
short_description: Manage backup schedules on Cisco Nexus Dashboard.

DOCUMENTATION = r"""
---
module: nd_backup_schedule
version_added: "0.5.0"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is 0.5.0 correct here? Should it be the next version of the collection instead?

description:
- The frequency at which remote backups are scheduled to occur at specified intervals on selected days.
- This parameter is required when creating the backup schedule.
type: int
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spec says that frequency is an enum of either 1,7 or 30 days. This is also consistent with the UI.
Should this be changed by adding choices of [1 7 30]?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants